-- Some Dope on Zope -- 
--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==


                               Zope и безопасность
                               =-=-=-=-=-=-=-=-=-=

Особо  распинаться про то, что такое Zope, я не планирую. Если вы еще не знакомы
с  этой  системой,  то  всю  необходимую  информацию  можно найти на официальном
web-сайте  [1].  В  двух  словах,  Zope - это полностью объектно-ориентированный
сервер  приложений  web,  почти  полностью написанный на языке Python [2], после
осознания  всех  возможностей которого все старания php-кодеров над собственными
CMS  вызывают  лишь улыбку и сочувствие. Данная статья посвящена обзору основных
встроенных средств безопасности Zope.

Zope  -  очень  защищенная  система.  Если посмотреть архивы багтрака на предмет
вопросов  безопасности,  связанных  с  этой  системой,  то  максимум чего смогли
добиться  сексперты,  так это инициировать трейсбек, содержащий физический путь,
по  которому  установлен  Zope  в системе при помощи всяких там кривых XML-RPC [
хотя  на самом деле есть куда более простые как локальные так и удаленные методы
получения  аналогичного результата, только какой от них смысл - в контексте Zope
это не дает ровным счетом ничего ].

С  самого начала Zope разрабатывалась как система многопользовательская, поэтому
там  реализовано  такое понятие как Роли [ Roles ], которые есть ни что иное как
ACL [ Access Control Lists ]. Благодаря ролям, назначаемым пользователям, в Zope
гораздо  проще организовать грамотный и безопасный workflow, в отличие от тех же
PHP   CMS,   где  каждый  автор  реализует  это  понятие  с  учетом  собственных
представлений что, как показала практика, не всегда есть лучший вариант.

По  умолчанию  Zope  имеет четыре роли - Manager, Owner [ различие лишь в уровне
доступа  к  объектам и методам ], Anonymous [ эту роль имеет любой пользователь,
не  авторизовавшийся  в  системе  ]  и  Authenticated  [  неявная  роль, которой
наделяется  любой  пользователь,  авторизованный в системе ]. Помимо этого также
существует  возможность создания Emergency User - пользователя, который не может
ничего,   кроме  как  создавать  других  пользователей  [  на  случай,  если  вы
забудете/лишитесь  )) пароля к своему основному пользователю с ролью Manager или
еще  что  ],  создать  которого  нельзя  через  интерфейс ZMI, только с консоли,
посредством  выполнения сценария zpasswd.py. Естесственно, вы имеете возможность
создания  новых  ролей  и  изменения уже существующих. Также каждый пользователь
может  иметь более одной роли. Говоря другими словами, каждый пользователь может
входить  в несколько групп пользователей, каждая группа которых наделена тем или
иным набором полномочий.

Zope  авторизует  пользователя  через  тип  авторизации,  именуемой  ``Zope''  [
аналогична  Basic  Auth  в  Apache ], хотя помимо этого существует еще несколько
встроенных  возможностей контроля доступа. В частности, для каждого пользователя
можно  указать конкретный IP или имя хоста [ равно как диапазон IP или имя хоста
вида  *.dialup.nigger.co.za ], с которых возможен доступ для этого пользователя.
То есть, если я работаю в Zope только с локальной машины, то я могу прописать IP
127.0.0.1  и  тогда  любой,  даже  знающий пароль этого пользователя, но имеющий
отличный от этого IP, не сможет получить доступа к интерфейсу управления Zope.
  
Для  организации  поддержания  сессии  пользователя  посредством  cookie,  можно
установить  продукт CookieCrumbler и добавить его экземпляр в папку, для доступа
к  которой необходимо авторизоваться. Об этом мы поговорим позже и рассмотрим на
примере  в  конце  статьи.  Сейчас же я хочу рассказать о создании новых ролей и
разновидностях полномочий.

Для  создания новой роли нужно перейти в Root Folder и выбрать вкладку Security.
На  этой  вкладке  перечислены все существующие роли и списки их полномочий. Вот
здесь  вы и можете вносить коррективы в существующие роли, то есть добавлять или
удалять  полномочия.  Однако  обращу  ваше  внимание,  что  в  Zope используется
механизм  наследования,  поэтому все изменения в доступе к Root Folder отразятся
на  всех  вложенных  в  нее  объектах.  К примеру, если вы лишите роли Anonymous
полномочия   на   доступ  к  объектам,  то  при  заходе  на  http://your_site.ru
пользователя   сперва  попросят  авторизоваться.  То  же  самое  относится  и  к
гипотетическому     объекту-папке,     расположенному     уровнем     ниже     -
http://your_site.ru/test_folder/.  Если  же вы хотите ограничить доступ только к
этой  папке,  то  вам  нужно перейти в нее через ZMI, выбрать вкладку Security и
убрать галочку напротив опции Access Transient Objects у роли Anonymous.
 
Так  или  иначе, на вкладке Security, в самом низу страницы есть небольшая форма
``User  defined  roles''. Введите в этом поле имя желаемой роли и нажмите кнопку
Add  role.  Теперь  рассмотрим сами доступные полномочия [ естесственно, по мере
добавления  в  систему новых продуктов, их состав будет изменяться ]. Вот список
основных,  наиболее  часто  используемых,  хотя на самом деле их гораздо больше.
Более   подробное   описание   каждого   из  объектов,  в  том  числе  здесь  не
перечисленных, смотрите в Zope Book [3].


Access Transient Objects
------------------------

Способность просматривать содержимое нерезидентных объектов.



Access contents information
---------------------------

Способность просматривать содержимое объекта. Это одно из ключевых полномочий.



Access session data
-------------------

Способность просматривать информацию о сессии пользователя.



Add Documents, Images, and Files
--------------------------------

Способность добавлять Документы, Изображения и Файлы.



Add External Methods
--------------------

Способность  добавлять  Внешние Методы. То есть средствами Zope вызывать внешние
программы,  не  являющиеся  объектами  Zope  и  расположенными где-то в файловой
системе, куда Zope имеет доступ.



Add Folders
-----------

Способность добавлять Папки - контейнеры объектов. 



Add MailHost objects
--------------------

Способность  добавлять  объекты  MailHost. Эти объекты используются для указания
почтового  релея,  через  который будут отправляться любые сообщения электронной
почты.  Это  удобно  при  использовании в различных сценариях получения обратной
связи от пользователей, etc.



Add Page Templates
------------------

Способность  добавлять  Шаблоны  Документов. В Zope имеется встроенный макроязык
шаблонов страниц [ ZPT ].



Add Python Scripts
------------------

Способность  добавлять Сценарии Python. Это не то же самое что и python CGI, так
что не путайте.



Add User Folders
----------------

Способность  добавлять  Специальный  объект  User  Folder, служащий для создания
механизма  авторизации  и  управления  пользователями. О нем будет сказано более
подробно  ниже.  Получить  имя пользователя, с которым тот вошел в систему можно
при   помощи   вызова   функции   SecurityGetUser().getUserName().  То  есть,  в
DTML-страницу/метод засовываем такой код:

Ваше имя: <dtml-var expr="_.SecurityGetUser().getUserName()">



Add Virtual Host Monsters
-------------------------

Способность  добавлять  VHM.  Virtual  Host  Monster  -  это объект, позволяющий
создавать виртуальные хосты без помощи Apache.
 


Add ZCatalogs
-------------

Способность добавлять объекты индексирования web-контента ZCatalog.



Add Zope Tutorials
------------------

Способность  добавлять  экземпляры  Zope Tutorial - руководства по использованию
Zope с примерами программ.



Change DTML Documents
---------------------

Способность изменять Документы DTML



Change DTML Methods
-------------------

Способность изменять Методы DTML.



Change External Methods
-----------------------

Способность изменять Внешние Методы.



Change Images and Files
-----------------------

Способность изменять Изображения и Файлы.



Change Page Templates
---------------------

Способность изменять Шаблоны Страниц.



Change Python Scripts
---------------------

Способность изменять Сценарии Python.



Change configuration
--------------------

Способность изменять конфигурацию.



Change permissions
------------------

Способность изменять права доступа.



Copy or Move
------------

Способность копировать или перемещать объекты.



Create Transient Objects
------------------------

Способность создавать нерезидентные объекты.



Create class instances
----------------------

Способность создавать экземпляры класса.



Define permissions
------------------

Способность определять права доступа.



Delete objects
--------------

Способность удалять объекты



FTP access
----------

Способность работы с Zope по протоколу FTP [ порт 8021 по умолчанию ].



Import/Export objects
---------------------

Способность импортировать и экспортировать объекты.



Log Site Errors
---------------

Способность регистрировать возникающие ошибки



Log to the Event Log
--------------------

Способность вести регистрацию событий



Manage Access Rules
-------------------

Способность управлять правилами доступа



Manage Z Classes
----------------

Способность управлять Z классами



Manage ZCatalog Entries
-----------------------

Способность управлять данными системы индексирования ZCatalog



Manage properties
-----------------

Способность изменять свойства объектов.



Manage users
------------

Способность управлять пользователями.



Open/Close Database Connection
------------------------------

Способность открывать/закрывать соединение с базой данных.



Search ZCatalog
---------------

Способность осуществлять поиск при помощи ZCatalog.



Take ownership
--------------

Способность становиться владельцем объекта.



Undo changes
------------

Способность отменять внесенные в объект изменения.



View
----

Способность просматривать объект.



View History
------------

Способность просматривать историю изменений объекта.



View management screens
-----------------------

Способность просматривать экраны управления объектами.



WebDAV access 
-------------

Способность доступа по протоколу WebDAV



Окей,  с этим разобрались. Теперь рассмотрим практическую задачу. К примеру, нам
нужно  создать архив приватной информации, доступ к которой будет осуществляться
по логину и паролю. В корне создадим объект-папку super_private. Теперь перейдем
в  нее, откроем вкладку Security и добавим новую роль, скажем, ``membah''. В эту
же  папку добавим объект User Folder, в нем создадим пользователя chuvak и дадим
ему  роль  membah.  Снова  открываем вкладку Security в папке super_private. Там
нужно  убрать  все  флажки,  соответствующие  роли  Anonymous. То же самое можно
проделать  и  с  другими  ролями,  главное  не  забыть  оставить себе доступ для
добавления  и  изменения  объектов, добавления пользователей, etc. Как вы можете
видеть, помимо четырех основном ролей, на вкладке Security теперь появилась роль
membah  - вот для нее и нужно установить соответствующие права. Предположим, что
все,  кому  мы дадим акаунт с ролью membah, будут только читать размещенную нами
информацию, но не будут иметь возможности ее добавления или изменения. Для этого
убираем  у  роли membah все кроме полномочий Access contents information и View.
По  желанию  также в папке User Folder определяем домен или IP, с которого будет
ходить наш пользователь chuvak.

Вот так. Теперь при попытке зайти по адресу http://your_site.ru/super_private/ у 
пользователя будут спрашивать логин и пароль.

Окей, теперь неплохо бы добавить поддержание сессии при помощи cookie. Для этого
установим   продукт   CookieCrumbler  [4]  и  поместим  его  экземпляр  в  папку
super_private  [  при  помощи ZMI ]. Теперь все готово к употреблению. Вы можете
использовать поставляющиеся с CookieCrumbler DTML-методы login_form, logged_in и
logged_out, а можете использовать свои. 

В конечном итоге у вас должна получиться примерно следующая минимальная иерархия
объектов:


[Root Folder]
  
  [super_pivate]

     [User folder]

        [chuvak]

     [CookieCrumbler]
       
     [logged_in] 
     
     [logged_out]

     [login_form]
     
     [index_html]


Окей.  Это  что  касается  встроенных средств. Но на самом деле ваши возможности
ограничиваются    только    вашим    воображением.    Предположим,   что   хакИр
угадал/узнал/подобрал  пароль  к пользователю chuvak, который, напомню, является
мембером  вашей  приватной  тусовки,  а поскольку чел сей меняет провайдеров как
перчатки,  вы  не  прописывали  в  свойствах  его  IP/dns.  Предотвратить  такое
можно,  к  примеру,  таким  вот  образом  -  мы  придумаем  какую-нить длинную и
непонятную   passphrase,   ну,   скажем,   ``l33t0^b0r1t0#%@(()!+_dd''  и  будем
показывать контент приват-зоны только тем, кто:

1. аутентифицирован
2. является членом группы(роли) membah
3. в поле HTTP_USER_AGENT имеет ту самую l33t0^b0r1t0#%@(()!+_dd

Если,  допустим, пользователь зашел с правильным паролем, но в HTTP_USER_AGENT у
него какой-нибудь там ``Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)'', то
мы  прописываем  ему  болт  и  демонстрируем  чудеса  JavaScript  ).  Как мы это
сделаем?? Легко. В каждую DTML страницу прописываем примерно следующее:

<dtml-if expr="REQUEST.get('HTTP_USER_AGENT') == 'l33t0^b0r1t0#%@(()!+_dd'">

 """
    здесь идет защищенный контент страницы
 """

  <dtml-else>

   <h1>.:"fuck 0ff n1gg4":.</h1>

     """
        а здесь идет какой-нибудь злой код ). напишите 
        сами или скопируйте из статьи о багах в IE
     """
  </dtml-else>

</dtml-if>

И так для каждой ``защищенной страницы''. Это тупой способ, но рабочий. Конечно,
все  можно  сделать гораздо красивей и приятней, к примеру, сохранить этот код в
отдельный  DTML  метод  и  вызывать  его в каждом документе по необходимости [ а
проще  добавить  его  вызов  в  standard_html_header  -  если вы не удаляете его
включение  из  каждого  создаваемого объекта ] и все дела. Тогда для смены вашей
passphrase вам понадобится изменить только этот метод и больше ничего.
Чтобы  не  усложнять  себе жизнь, я оставляю реализацию этого способа в качестве
вашего  домашнего  задания.  Плагины  для изменения HTTP_USER_AGENT для браузера
Mozilla  Firebird  можно  взять  на  странице с плагинами Mozilla'ы - там их как
минимум два, а то и больше, да и для IE, я думаю, есть что-то подобное.

На этом все. Если эта тема будет кому-либо интересна, то, возможно, статья будет
иметь продолжение в последующих выпусках D.


Ссылки
------

[1] Официальный web-сайт Zope  -  www.zope.org

[2] Официальный сайт Python  -  www.python.org

[3] Zope Book  -  http://zope.org/Documentation/Books/ZopeBook/2_6Edition/

[4] CookieCrumbler  -  http://hathaway.freezope.org/Software/CookieCrumbler